/*--------------------------------------------- Noble Steed Engine--------------------------------------*
Authors : Daniel Randle, Alex Bourne
Date Created : April 09 2013

File:
	nscamera.cpp

Description:
	This file contains the definition for the NSMapBuilder class and any associated functions that help
	the ol' girl out
*-----------------------------------------------------------------------------------------------------*/

#include <nsmapbuilder.h>
#include <nsobjectreference.h>
#include <nsmaparea.h>
#include <nsengine.h>

#ifdef DEBUG
#include <debug.h>
#endif

/*-----------------------------*
|   class NSMapBuilder BEGINS  |
*------------------------------*/

NSMapBuilder::NSMapBuilder(NSMapArea * map):mapArea(map),
	refToAdd(NULL),
	buildObj(NULL),
	activated(false)
{}

bool NSMapBuilder::activate(const NSVec3Df & position, const NSVec3Df & orientation, const NSVec3Df & scale)
{
	NSEngine * eng = mapArea->getEngine();
	if (buildObj == NULL) // tried to activate without setting the base object
	{
		activated = false;
		return activated;
	}
	// Create new reference from the base object with the passed in position, size, and scale
	refToAdd = eng->createReference(buildObj,position, orientation, scale);
	refToAdd->setProjectionMat(mapArea->getEngine()->getProjectionMatrix());
	activated = true;
	return activated;
}

bool NSMapBuilder::addToMap()
{
	if (refToAdd == NULL) // tried to add reference to map without activating the build tool
		return false;
	
	// Take the reference from refToAdd and transfer ownership to the mapArea
	mapArea->addReference(refToAdd);

	// Create a new reference to take the place of the other one.. new reference will have same position
	// as old reference only moved by a z factor of 1 if tile - FUTURE: Will let collision decide where to put new reference
	activate(refToAdd->getPosition(),refToAdd->getOrientation(),refToAdd->getScale());
	return true;
}

bool NSMapBuilder::deactivate()
{
	if (refToAdd == NULL)  // most likely build tool tried to be used without activation
	{
		activated = true;
		return !activated;
	}

	// This is assuming that the reference object is always the last transform in the object's transform list..
	// This should always be kept true no matter what or the engine will crash
	refToAdd->remove(); // removes the transform from the object transform list
	delete refToAdd;
	refToAdd = NULL;
	activated = false;
	return !activated;
}

bool NSMapBuilder::isActivated()
{
	return activated;
}

NSObject * NSMapBuilder::getObject()
{
	return buildObj;
}

NSVec3Df  NSMapBuilder::getPosition()
{
	if (refToAdd != NULL)
		return refToAdd->getPosition();
	return NSVec3Df();
}

NSObjectReference * NSMapBuilder::getReference(unsigned int refID)
{
	// Check if ref is NULL - if not then check ID
	// if match - return ref otherwise return NULL
	if (refToAdd != NULL)
	{
		if (refToAdd->getID() == refID)
			return refToAdd;
		else
			return NULL;
	}
	// NULL for no ref found
	return NULL;
}

void NSMapBuilder::moveXYFromMouse(const NSVec2Df & currentMousePos, const NSVec2Df & lastMousePos)
{
	if (refToAdd == NULL || buildObj == NULL)
		return;
	// First get the engine pointer
	NSEngine * engine = mapArea->getEngine();

	// Then use that pointer to get the normalized device coordinates for the mouse and use that to move the reference
	// according to the mouse movement
	refToAdd->moveXYFromMouseNDC(engine->getNDCFromMousePos(currentMousePos),engine->getNDCFromMousePos(lastMousePos),engine->getCamera());
}

void NSMapBuilder::moveZFromMouse(const NSVec2Df & currentMousePos, const NSVec2Df & lastMousePos)
{
	if (refToAdd == NULL || buildObj == NULL)
		return;

	// First get the engine pointer
	NSEngine * engine = mapArea->getEngine();

	// Now get normalized device coordinates with the engine and move the reference in the z direction according
	// to mouse movement
	refToAdd->moveZFromMouseNDC(engine->getNDCFromMousePos(currentMousePos),engine->getNDCFromMousePos(lastMousePos),engine->getCamera());
}

void NSMapBuilder::rotate(const NSVec3Df & amount)
{
	refToAdd->rotate(amount);
}

void NSMapBuilder::scale(const NSVec3Df & amount)
{
	refToAdd->scale(amount);
}

bool NSMapBuilder::setObject(NSObject * obj)
{
	// If tried to set to uninitialized pointer or object then return false
	// Probably no selected object - thats okay just need to set object to NULL
	buildObj = obj;
	if (buildObj != NULL && buildObj->isHasMesh())
		return true;
	buildObj = NULL; // restore to null in case object existed but didnt have mesh
	return false;
}

void NSMapBuilder::translate(const NSVec3Df & amount)
{
	refToAdd->translate(amount);
}

void NSMapBuilder::update()
{
	if (refToAdd != NULL)
		refToAdd->update();
}
